1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.primitives;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkElementIndex;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkPositionIndexes;
23
24 import com.google.common.annotations.GwtCompatible;
25
26 import java.io.Serializable;
27 import java.util.AbstractList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Comparator;
31 import java.util.List;
32 import java.util.RandomAccess;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 @GwtCompatible(emulated = true)
49 public final class Chars {
50 private Chars() {}
51
52
53
54
55
56 public static final int BYTES = Character.SIZE / Byte.SIZE;
57
58
59
60
61
62
63
64
65 public static int hashCode(char value) {
66 return value;
67 }
68
69
70
71
72
73
74
75
76
77 public static char checkedCast(long value) {
78 char result = (char) value;
79 if (result != value) {
80
81 throw new IllegalArgumentException("Out of range: " + value);
82 }
83 return result;
84 }
85
86
87
88
89
90
91
92
93
94 public static char saturatedCast(long value) {
95 if (value > Character.MAX_VALUE) {
96 return Character.MAX_VALUE;
97 }
98 if (value < Character.MIN_VALUE) {
99 return Character.MIN_VALUE;
100 }
101 return (char) value;
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public static int compare(char a, char b) {
117 return a - b;
118 }
119
120
121
122
123
124
125
126
127
128
129 public static boolean contains(char[] array, char target) {
130 for (char value : array) {
131 if (value == target) {
132 return true;
133 }
134 }
135 return false;
136 }
137
138
139
140
141
142
143
144
145
146
147 public static int indexOf(char[] array, char target) {
148 return indexOf(array, target, 0, array.length);
149 }
150
151
152 private static int indexOf(
153 char[] array, char target, int start, int end) {
154 for (int i = start; i < end; i++) {
155 if (array[i] == target) {
156 return i;
157 }
158 }
159 return -1;
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173 public static int indexOf(char[] array, char[] target) {
174 checkNotNull(array, "array");
175 checkNotNull(target, "target");
176 if (target.length == 0) {
177 return 0;
178 }
179
180 outer:
181 for (int i = 0; i < array.length - target.length + 1; i++) {
182 for (int j = 0; j < target.length; j++) {
183 if (array[i + j] != target[j]) {
184 continue outer;
185 }
186 }
187 return i;
188 }
189 return -1;
190 }
191
192
193
194
195
196
197
198
199
200
201 public static int lastIndexOf(char[] array, char target) {
202 return lastIndexOf(array, target, 0, array.length);
203 }
204
205
206 private static int lastIndexOf(
207 char[] array, char target, int start, int end) {
208 for (int i = end - 1; i >= start; i--) {
209 if (array[i] == target) {
210 return i;
211 }
212 }
213 return -1;
214 }
215
216
217
218
219
220
221
222
223
224 public static char min(char... array) {
225 checkArgument(array.length > 0);
226 char min = array[0];
227 for (int i = 1; i < array.length; i++) {
228 if (array[i] < min) {
229 min = array[i];
230 }
231 }
232 return min;
233 }
234
235
236
237
238
239
240
241
242
243 public static char max(char... array) {
244 checkArgument(array.length > 0);
245 char max = array[0];
246 for (int i = 1; i < array.length; i++) {
247 if (array[i] > max) {
248 max = array[i];
249 }
250 }
251 return max;
252 }
253
254
255
256
257
258
259
260
261
262
263 public static char[] concat(char[]... arrays) {
264 int length = 0;
265 for (char[] array : arrays) {
266 length += array.length;
267 }
268 char[] result = new char[length];
269 int pos = 0;
270 for (char[] array : arrays) {
271 System.arraycopy(array, 0, result, pos, array.length);
272 pos += array.length;
273 }
274 return result;
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293 public static char[] ensureCapacity(
294 char[] array, int minLength, int padding) {
295 checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
296 checkArgument(padding >= 0, "Invalid padding: %s", padding);
297 return (array.length < minLength)
298 ? copyOf(array, minLength + padding)
299 : array;
300 }
301
302
303 private static char[] copyOf(char[] original, int length) {
304 char[] copy = new char[length];
305 System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
306 return copy;
307 }
308
309
310
311
312
313
314
315
316
317
318 public static String join(String separator, char... array) {
319 checkNotNull(separator);
320 int len = array.length;
321 if (len == 0) {
322 return "";
323 }
324
325 StringBuilder builder
326 = new StringBuilder(len + separator.length() * (len - 1));
327 builder.append(array[0]);
328 for (int i = 1; i < len; i++) {
329 builder.append(separator).append(array[i]);
330 }
331 return builder.toString();
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350 public static Comparator<char[]> lexicographicalComparator() {
351 return LexicographicalComparator.INSTANCE;
352 }
353
354 private enum LexicographicalComparator implements Comparator<char[]> {
355 INSTANCE;
356
357 @Override
358 public int compare(char[] left, char[] right) {
359 int minLength = Math.min(left.length, right.length);
360 for (int i = 0; i < minLength; i++) {
361 int result = Chars.compare(left[i], right[i]);
362 if (result != 0) {
363 return result;
364 }
365 }
366 return left.length - right.length;
367 }
368 }
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384 public static char[] toArray(Collection<Character> collection) {
385 if (collection instanceof CharArrayAsList) {
386 return ((CharArrayAsList) collection).toCharArray();
387 }
388
389 Object[] boxedArray = collection.toArray();
390 int len = boxedArray.length;
391 char[] array = new char[len];
392 for (int i = 0; i < len; i++) {
393
394 array[i] = (Character) checkNotNull(boxedArray[i]);
395 }
396 return array;
397 }
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413 public static List<Character> asList(char... backingArray) {
414 if (backingArray.length == 0) {
415 return Collections.emptyList();
416 }
417 return new CharArrayAsList(backingArray);
418 }
419
420 @GwtCompatible
421 private static class CharArrayAsList extends AbstractList<Character>
422 implements RandomAccess, Serializable {
423 final char[] array;
424 final int start;
425 final int end;
426
427 CharArrayAsList(char[] array) {
428 this(array, 0, array.length);
429 }
430
431 CharArrayAsList(char[] array, int start, int end) {
432 this.array = array;
433 this.start = start;
434 this.end = end;
435 }
436
437 @Override public int size() {
438 return end - start;
439 }
440
441 @Override public boolean isEmpty() {
442 return false;
443 }
444
445 @Override public Character get(int index) {
446 checkElementIndex(index, size());
447 return array[start + index];
448 }
449
450 @Override public boolean contains(Object target) {
451
452 return (target instanceof Character)
453 && Chars.indexOf(array, (Character) target, start, end) != -1;
454 }
455
456 @Override public int indexOf(Object target) {
457
458 if (target instanceof Character) {
459 int i = Chars.indexOf(array, (Character) target, start, end);
460 if (i >= 0) {
461 return i - start;
462 }
463 }
464 return -1;
465 }
466
467 @Override public int lastIndexOf(Object target) {
468
469 if (target instanceof Character) {
470 int i = Chars.lastIndexOf(array, (Character) target, start, end);
471 if (i >= 0) {
472 return i - start;
473 }
474 }
475 return -1;
476 }
477
478 @Override public Character set(int index, Character element) {
479 checkElementIndex(index, size());
480 char oldValue = array[start + index];
481
482 array[start + index] = checkNotNull(element);
483 return oldValue;
484 }
485
486 @Override public List<Character> subList(int fromIndex, int toIndex) {
487 int size = size();
488 checkPositionIndexes(fromIndex, toIndex, size);
489 if (fromIndex == toIndex) {
490 return Collections.emptyList();
491 }
492 return new CharArrayAsList(array, start + fromIndex, start + toIndex);
493 }
494
495 @Override public boolean equals(Object object) {
496 if (object == this) {
497 return true;
498 }
499 if (object instanceof CharArrayAsList) {
500 CharArrayAsList that = (CharArrayAsList) object;
501 int size = size();
502 if (that.size() != size) {
503 return false;
504 }
505 for (int i = 0; i < size; i++) {
506 if (array[start + i] != that.array[that.start + i]) {
507 return false;
508 }
509 }
510 return true;
511 }
512 return super.equals(object);
513 }
514
515 @Override public int hashCode() {
516 int result = 1;
517 for (int i = start; i < end; i++) {
518 result = 31 * result + Chars.hashCode(array[i]);
519 }
520 return result;
521 }
522
523 @Override public String toString() {
524 StringBuilder builder = new StringBuilder(size() * 3);
525 builder.append('[').append(array[start]);
526 for (int i = start + 1; i < end; i++) {
527 builder.append(", ").append(array[i]);
528 }
529 return builder.append(']').toString();
530 }
531
532 char[] toCharArray() {
533
534 int size = size();
535 char[] result = new char[size];
536 System.arraycopy(array, start, result, 0, size);
537 return result;
538 }
539
540 private static final long serialVersionUID = 0;
541 }
542 }